﻿Imports System.Reflection
Imports System.Text.RegularExpressions

''' <summary>
''' キー属性生成クラス
''' </summary>
''' <remarks></remarks>
Public Class KeyAttributeFactory
    ''' <summary>
    ''' キー属性を生成します。
    ''' </summary>
    ''' <param name="prop"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' 指定がある場合はそちらが優先され、指定がない場合は自動生成します。
    ''' </remarks>
    Public Function Create(ByVal prop As PropertyInfo) As List(Of KeyAttribute)
        '指定属性
        Dim manuals As List(Of KeyAttribute) = AttributeReader.Read(Of KeyAttribute)(prop).ToList

        If manuals IsNot Nothing AndAlso manuals.Any Then Return manuals

        '制約上属性
        Dim masters As List(Of KeyAttribute) = If(PropertyReader.IsParent(prop), CreateParentMaster(prop), CreateNormalMaster(prop))

        '指定がない場合は、制約上の属性を返却。
        Return masters
    End Function

    ''' <summary>
    ''' 制約上の属性を取得します。
    ''' </summary>
    ''' <param name="prop"></param>
    ''' <returns></returns>
    ''' <remarks>制約を上書きできるよう、Overridableとします。</remarks>
    Protected Overridable Function CreateNormalMaster(prop As PropertyInfo) As List(Of KeyAttribute)
        Dim lst As New List(Of KeyAttribute)

        Dim seqPattern = String.Format("^(SID|{0}SID|Sid|{0}Sid|SEQ|{0}SEQ|Seq|{0}Seq)$", prop.DeclaringType.Name)
        If Regex.IsMatch(prop.Name, seqPattern) Then
            Dim s = Kairyu.Connection.KairyuSectionHandlerFactory.Create.ExecutionEnvironment.DBMS
            Dim key As KeyAttribute = Nothing
            Dim name = String.Format("SQ_{0}", prop.DeclaringType.ToTable.TableName)
            Select Case s
                Case Connection.DBMS.SqlServer2012
                    key = New Kairyu.SQLServerSequenceKeyAttribute(name)
                Case Connection.DBMS.Oracle
                    key = New Kairyu.OracleSequenceKeyAttribute(name)
                Case Else
                    key = New KeyAttribute
            End Select
            lst.Add(key)
            Return lst
        End If

        Dim idPattern As String = String.Format("^(ID|{0}ID|Id|{0}Id)$", prop.DeclaringType.Name)
        If Regex.IsMatch(prop.Name, idPattern) Then
            lst.Add(New KeyAttribute)
            Return lst
        End If

        Return lst
    End Function

    Private Function CreateParentMaster(prop As PropertyInfo) As List(Of KeyAttribute)
        Dim lst As New List(Of KeyAttribute)

        'Extension制約によるキー判定
        If prop.Name = "Base" Then
            Dim parentType = prop.PropertyType
            Dim childType = prop.DeclaringType
            Dim q = (From el In parentType.GetProperties Where PropertyReader.IsChild(el) AndAlso el.PropertyType.GetGenericArguments.First.Equals(childType))
            If q.Count = 1 AndAlso PropertyReader.IsExtensionCollection(q.First) Then
                lst.Add(New KeyAttribute)
                Return lst
            End If
        End If

        Dim name = prop.DeclaringType.Name

        Dim m = Regex.Match(prop.DeclaringType.Name, String.Format("(^(?<other>.+)(Combination|Inner|N){0}$|^{0}(Combination|Inner|N)(?<other>.+)$)", prop.Name))

        If m.Success AndAlso (From el In prop.DeclaringType.GetProperties Where el.Name = m.Groups("other").Value).Any Then
            lst.Add(New KeyAttribute)
        End If

        Return lst
    End Function

End Class
